package com.util;

import java.lang.reflect.*;
import java.util.*;
import java.sql.*;

public class JDBCUtil {

	/**
	 * 将ResultSet转换为泛型集合
	 * @param c
	 * @param set
	 * @return
	 */
	public static <T> List<T> convertResultSetToList(Class<T> c, ResultSet set){
		List<T> list = new ArrayList<T>();
		//获取所有属性
		Field[] fileds = c.getDeclaredFields();
		try {
			while(set.next()){
				//利用反射自动创建实体对象
				T instance = (T)c.newInstance();
				//遍历所有字段
				for(Field field : fileds){
					invokeFieldSetMethod(instance, field, set);
				}
				list.add(instance);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return list;
	}
	
	/**
	 * 从ResultSet中提取第一条记录，并转换为实体对象
	 * @param c
	 * @param set
	 * @return
	 */
	public static <T> T convertResultSetToEntity(Class<T> c, ResultSet set){
		//获取所有属性
		Field[] fileds = c.getDeclaredFields();
		
		try {
			while(set.next()){
				//利用反射自动创建实体对象
				T instance = (T)c.newInstance();
				//遍历所有字段
				for(Field field : fileds){
					invokeFieldSetMethod(instance, field, set);
				}
				return instance;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}
	
	
	/**
	 * 执行字段的setter方法
	 * @param instance
	 * @param field
	 * @param set
	 */
	private static void invokeFieldSetMethod(Object instance, Field field, ResultSet set){
		try{
			//获取字段的setter方法名称
			String methodName = "set"+field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
			//获取字段的setter方法
			Method getMethod = instance.getClass().getMethod(methodName, field.getType());
						//获取字段的类型名称（不包含包名）
			String typeName = field.getType().toString().toLowerCase();
			typeName = typeName.substring(typeName.lastIndexOf(".")+1);			
			if(typeName.equals("int")||typeName.equals("integer")){
				//执行setter方法
				getMethod.invoke(instance, set.getInt(field.getName()));
			}else if(typeName.equals("short")){
				getMethod.invoke(instance, set.getShort(field.getName()));
			}else if(typeName.equals("byte")){
				getMethod.invoke(instance, set.getByte(field.getName()));
			}else if(typeName.equals("long")){
				getMethod.invoke(instance, set.getLong(field.getName()));
			}else if(typeName.equals("float")){
				getMethod.invoke(instance, set.getFloat(field.getName()));
			}else if(typeName.equals("double")){
				getMethod.invoke(instance, set.getDouble(field.getName()));
			}else if(typeName.equals("date")){
				getMethod.invoke(instance, set.getDate(field.getName()));
			}else if(typeName.equals("string")){
				getMethod.invoke(instance, set.getString(field.getName()));
			}else if(typeName.equals("boolean")){
				getMethod.invoke(instance, set.getBoolean(field.getName()));
			}else{
				getMethod.invoke(instance, set.getObject(field.getName()));
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
	
	public static <T> List<T> resultToList(ResultSet resultSet, Class<T> clazz) {
		// 创建一个 T 类型的数组
		List<T> list = new ArrayList<>();
		try {
			// 通过反射获取对象的实例
			T t = clazz.getConstructor().newInstance();
			// 获取resultSet 的列的信息
			ResultSetMetaData metaData = resultSet.getMetaData();
			// 遍历resultSet
			while (resultSet.next()) {
				// 遍历每一列
				for (int i = 0; i < metaData.getColumnCount(); i++) {
					// 获取列的名字
					String fName = metaData.getColumnLabel(i + 1);
					// 因为列的名字和我们EMP中的属性名是一样的，所以通过列的名字获得其EMP中属性
					Field field = clazz.getDeclaredField(fName.toLowerCase());
					// 因为属性是私有的，所有获得其对应的set 方法。set+属性名首字母大写+其他小写
					String setName = "set" + fName.toUpperCase().substring(0, 1) + fName.substring(1).toLowerCase();
					// 因为属性的类型和set方法的参数类型一致，所以可以获得set方法
					Method setMethod = clazz.getMethod(setName, field.getType());
					// 执行set方法，把resultSet中的值传入emp中， 再继续循环传值
					setMethod.invoke(t, resultSet.getObject(fName));
				}
				// 把赋值后的对象 加入到list集合中
				list.add(t);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		// 返回list
		return list;
	}
}
